home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / xview / segal / cmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-21  |  14.0 KB  |  601 lines

  1. /*
  2.  * cmap.c -- routines for manipulating colormap
  3.  *
  4.  * general steps involved in creating ximage with proper color:
  5.  *   1) read data
  6.  *   2) create buffer of gray-level lut indices (make_lut)
  7.  *   3) create colormap of these colors (build_colormap)
  8.  *   4) create buffer of colormap lut indices (map_image_to_colors)
  9.  *   5) create ximage (mk_x_img)
  10.  */
  11.  
  12. #include "common.h"
  13.  
  14. /* colors must go in order of the list in common.h */
  15. char     *palnames[PALSIZE] =
  16. {
  17.     "red",
  18.     "brown",
  19.     "orange",
  20.     "yellow",
  21.     "medium forest green",
  22.     "turquoise",
  23.     "blue",
  24.     "purple",
  25.     "black",
  26.     "white"
  27. };
  28.  
  29. static XColor    pallet[PALSIZE];
  30. u_long   *colors;
  31.  
  32. byte      red[256], green[256], blue[256];
  33.  
  34. u_long   *build_colormap();
  35.  
  36. /* global colormap creation modes */
  37. /* see xcolor.c for a better explaination of these flags */
  38. static int numcol = 256;    /* # desired colors in the picture */
  39. static int noglob = FALSE;    /* allows color flashing */
  40. static int perfect = FALSE;    /* create all colors asked for? */
  41. static int ncols = 245;        /* max # colos to try to allocate */
  42. static int rwcolor = FALSE;    /* can other prg realloc the colormap? */
  43. static int mono = FALSE;    /* convert all colors to grayscale? */
  44. static int use_all = TRUE;    /* use all colors in the cmap, even though
  45.                  * not used in this frame? */
  46. vb = TRUE;            /* Give important messages */
  47.  
  48. /*************************************************************/
  49. void
  50. cmap_init()
  51. {
  52.     LOGIC rgb_too_close();
  53.  
  54.     Colormap cmap;
  55.     int i, j, k, val;
  56.     double gammaval = 1.0;
  57.     int r, g, b;
  58.     int gh = 0, rh = 0;        /* HSV values */
  59.     double gs = 1., gv = 1., rs = 1., rv = 1.;
  60.     extern int overlay_hue;    /* command line arg - make 1 for rh later */
  61.  
  62.     printf(" initializing colormap \n");
  63.  
  64.     mainw = win[WIN_VZ].xid;
  65.  
  66.     cmap = XDefaultColormap(display, screen);
  67.  
  68.     /* set up standout colors (read-only colors) */
  69.     for (i = 0; i < PALSIZE; i++) {
  70.         if (XParseColor(display, cmap, palnames[i], &pallet[i]) == 0)
  71.             fprintf(stderr, "%s: Error parsing color \n", Progname);
  72.         else if (XAllocColor(display, cmap, &pallet[i]) == 0)
  73.             fprintf(stderr, "%s: couldn't allocate color: %s.\n",
  74.                 Progname, palnames[i]);
  75.     }
  76.  
  77.     gammaval = (float) xv_get(Preferences_pop_preferences_display->set_image_contrast, PANEL_VALUE, NULL) / 10.;
  78.  
  79.     for (i = 0; i < NUM_GRAY; i++) { /* mask-image blend colors*/
  80.         /* hsv model seems to work better */
  81.         gh = overlay_hue;    /* greenish */
  82.         gs = .8;
  83.  
  84.         /* .5 to 1.0 */
  85.         gv = .5 + (.5 * (float) i / NUM_GRAY.);
  86.  
  87.         HSV_to_RGB((short) gh, gs, gv, &r, &g, &b);
  88.  
  89.         red[i] = (u_char) r;
  90.         green[i] = (u_char) g;
  91.         blue[i] = (u_char) b;
  92.     }
  93.  
  94.     for (i = 0; i < NUM_GRAY; i++) {/* pt_list-image blend colors */
  95.         rh = 0;            /* redish */
  96.         rs = .8;
  97.  
  98.         /* .5 to 1.0 */
  99.         rv = .5 + (.5 * (float) i / NUM_GRAY.);
  100.  
  101.         HSV_to_RGB((short) rh, rs, rv, &r, &g, &b);
  102.  
  103.         k = i + NUM_GRAY;
  104.         red[k] = (u_char) r;
  105.         green[k] = (u_char) g;
  106.         blue[k] = (u_char) b;
  107.     }
  108.  
  109.     if(segal.color) {
  110.         vprint"*** putting colors into red, green, and blue arrays\n");
  111.  
  112.         /* put the most frequent colors in ... */
  113.         i = 0; /* number of colors pulled out of rgb.histo */
  114.         j = 0; /* index to the rgb.histo[] */
  115.         while(i < rgb.quant.num_from_histo && j < rgb.num_histo) {
  116.             k = i + NUM_GRAY * 2;
  117.             /* make sure colors are "distinct" enough */
  118.             if(!rgb_too_close(k, rgb.histo[j].r,
  119.             rgb.histo[j].g, rgb.histo[j].b)) {
  120.                 red[k] = (u_char) rgb.histo[j].r;
  121.                 green[k] = (u_char) rgb.histo[j].g;
  122.                 blue[k] = (u_char) rgb.histo[j].b;
  123.  
  124.                 /* remember where we just put this triple */
  125.                 rgb.histo[j].col_i = k;
  126.                 i++;
  127.             }
  128.             j++;
  129.         }
  130.  
  131.         /* put the automatic-assigment colors in ... */
  132.         for(i = 0, r = 1; r <= rgb.quant.auto_r; r++)
  133.         for(g = 1; g <= rgb.quant.auto_g; g++)
  134.         for(b = 1; b <= rgb.quant.auto_b; b++, i++) {
  135.             k = i + NUM_GRAY * 2 + rgb.quant.num_from_histo;
  136.             red[k] = (u_char) ((float) r * 
  137.                 255. / (float) rgb.quant.auto_r);
  138.             green[k] = (u_char) ((float) g *
  139.                 255. / (float) rgb.quant.auto_g);
  140.             blue[k] = (u_char) ((float) b *
  141.                 255. / (float) rgb.quant.auto_b);
  142.         }
  143.     }
  144.     else {
  145.         vprint"*** putting grays into red, green, and blue arrays\n");
  146.         for (i = 0; i < NUM_GRAY; i++) {
  147.         /* straight gray values */
  148.             if (gammaval == 1.0)
  149.                 j = (int) ((i * 257.) / NUM_GRAY.);
  150.             else
  151.                 j = (int) (257. * pow((double) i / NUM_GRAY.,
  152.                     1.0 / gammaval));
  153.             if (j > 255) j = 255;
  154.  
  155.             k = i + NUM_GRAY * 2;
  156.             red[k] = blue[k] = green[k] = (u_char) j;
  157.         }
  158.     }
  159. }
  160.  
  161. /*************************************************************/
  162. LOGIC
  163. rgb_too_close(num_cols, r, g, b)
  164. int num_cols;
  165. byte r, g, b;
  166. {
  167. /* Searches the red[]. green[], and blue[] alloc'd colors to make sure that
  168.  * this candidate r,g,b is far apart from them ... so we don't waste colors
  169.  * for allocating
  170.  */
  171.     int i;
  172.  
  173.     for(i = 0; i < num_cols; i++)
  174.         /* too close to an existing color? */
  175.         if(DISTANCE(r, g, b, red[i], green[i], blue[i])
  176.             < rgb.quant.min_rgb_dist)
  177.             return(TRUE);
  178.  
  179.     /* else found a successful candidate r,g,b */
  180.     return(FALSE);
  181. }
  182.  
  183. /*************************************************************/
  184. void
  185. build_cmap()
  186. {
  187.     void make_luts();
  188.     void scale_image();
  189. #ifdef DEBUG
  190.     void show_colormap();
  191. #endif
  192.     printf("*** building colormap ...\n");
  193.  
  194.     vprint"*** making lut's\n");
  195.     make_luts();
  196.  
  197.     /* creates image_map (the colormap for the image) */
  198.     /* I'm not sure this needs to remain in the program - Bryan */
  199.     /*
  200.     printf("*** scaling image ...\n");
  201.     scale_image(win[WIN_VZ].i_data[0], image_map, NUM_GRAY);
  202.     */
  203.  
  204.     printf("*** defining colors ... \n");
  205.     colors = build_colormap(display, winv, mainw,
  206.         (byte *) image_map, win[WIN_VZ].img_size,
  207.         red, green, blue, numcol,
  208.         noglob, perfect, ncols, mono, use_all, rwcolor,
  209.         vb, Progname);
  210.  
  211.     printf(" colors defined ...\n");
  212. #ifdef DEBUG
  213.     show_colormap();
  214. #endif
  215.  
  216. return;
  217. }
  218.  
  219. /************************************************/
  220. void
  221. scale_image(image_data, image_map, ncols)
  222. byte *image_data, *image_map;
  223. int ncols;
  224. {
  225. /* This fn could probably be replaced by a loop of lookups to the lut's */
  226. /* Creates an image of colormap lookup values (array indices) */
  227.     register int i, j;
  228.     float     delta = (float) (ncols - 1) / 256.0;
  229.  
  230.     if(segal.color) {
  231.     }
  232.     else {
  233.         for (i = 0; i < win[WIN_VZ].img_size; i++) {
  234.             j = (int) image_data[i];
  235.             image_map[i] = (byte) (j * delta);
  236.         }
  237.     }
  238.     return;
  239. }
  240.  
  241. /************************************************/
  242. void
  243. make_luts()
  244. {
  245.     byte ***alloc_3d_byte_array();
  246.     byte closest_rgb_used();
  247.  
  248.     register int i, j, k;
  249.     float scale1, scale2;
  250.  
  251.     scale1 = (((float) xv_get(Preferences_pop_preferences_display->set_image_opacity, PANEL_VALUE, NULL) / 100.) * NUM_GRAY.) / 257.;
  252.     scale2 = (((float) xv_get(Preferences_pop_preferences_display->set_mask_opacity, PANEL_VALUE, NULL) / 100.) * NUM_GRAY.) / 257.;
  253.  
  254.     /* CHANGE - figure out better ways to do all this */
  255.     scale2 = .25;
  256. vprint"scale1 = %f, scale2 = %f\n", scale1, scale2);
  257.  
  258.     if(segal.color) {
  259.         vprint"*** allocating rgb.map\n");
  260.  
  261.         if(rgb.map != NULL) {
  262.             free_3d_byte_array(rgb.map);
  263.             rgb.map = NULL;
  264.         }
  265.         rgb.map = alloc_3d_byte_array(rgb.map_r, rgb.map_g, rgb.map_b);
  266.  
  267.         for(i = 0; i < rgb.map_r; i++)
  268.         for(j = 0; j < rgb.map_g; j++)
  269.         for(k = 0; k < rgb.map_b; k++)
  270.             rgb.map[i][j][k] = UNDEFINED_BYTE;
  271.     }
  272.  
  273.     /* make gray, points, and blend luts */
  274.     vprint"*** building gray, points, and blend luts\n");
  275.     for (i = 0; i < 256; i++) {
  276.         k = i * scale1;
  277.         if (k >= NUM_GRAY)
  278.             k = NUM_GRAY - 1;
  279.         gray_lut[i] = 2 * NUM_GRAY + k;
  280.  
  281.         k = i * scale2;
  282.         if (k >= NUM_GRAY)
  283.             k = NUM_GRAY - 1;
  284.         blend_lut[i] = k;
  285.         pt_lut[i] = NUM_GRAY + k;
  286.     }
  287. }
  288.  
  289. /************************************************/
  290. byte
  291. closest_rgb_used(r, g, b)
  292. byte r, g, b;
  293. {
  294. /* search for the closest r,g,b in used, and return col_i */
  295.     int i, min_i;
  296.     double dist, min_dist, total_colors;
  297.  
  298.     min_i = 0;
  299.     min_dist = DISTANCE(0, 0, 0, 256, 256, 256);
  300.  
  301.     if(segal.color) total_colors = 2 * NUM_GRAY + rgb.quant.num_from_histo
  302.         + (rgb.quant.auto_r * rgb.quant.auto_r * rgb.quant.auto_b);
  303.     else total_colors = 3 * NUM_GRAY;
  304.  
  305.     for(i = 0; i < total_colors; i++) {
  306.         dist = DISTANCE(r, g, b, red[i], green[i], blue[i]);
  307.         if(dist < min_dist) {
  308.             min_i = i;
  309.             min_dist = dist;
  310.         }
  311.     }
  312.     return(min_i);
  313. }
  314.  
  315. /************************************************/
  316. byte
  317. map_rgb_to_xcolor(r, g, b)
  318. byte r, g, b;
  319. {
  320. /* Given r, g, b, this uses the rgbmap to find the appropriate color in the
  321.  * colors[].
  322.  */
  323.     byte closest_rgb_used();
  324.  
  325.     float rx, gx, bx;
  326.     int rm, gm, bm;
  327.     byte i;
  328.  
  329.     if(rgb.map == NULL) return(0);
  330.  
  331.     rx = (float) rgb.map_r / 256.;
  332.     gx = (float) rgb.map_g / 256.;
  333.     bx = (float) rgb.map_b / 256.;
  334.  
  335.     /* indexes to rgb.map */
  336.     rm = (int) ((float) r * rx);
  337.     gm = (int) ((float) g * gx);
  338.     bm = (int) ((float) b * bx);
  339.  
  340.     i = rgb.map[rm][gm][bm];
  341.     if(i == UNDEFINED_BYTE)
  342.     /* find the closest allocated color and fill in this lattice point */
  343.         i = rgb.map[rm][gm][bm] = closest_rgb_used(r, g, b);
  344.  
  345.     return(i);
  346. }
  347.  
  348. /************************************************/
  349. void
  350. map_image_to_buf(image, buf, rows, cols)
  351. byte ***image, **buf;
  352. int rows, cols;
  353. {
  354. /* map image thru color indexes to buf data */
  355.     byte map_rgb_to_xcolor();
  356.  
  357.     register int r, c;
  358.  
  359.     if(segal.color) for(r = 0; r < rows; r++)
  360.         for(c = 0; c < cols; c++)
  361.         buf[r][c] = (byte) colors[map_rgb_to_xcolor(image[RP][r][c],
  362.             image[GP][r][c], image[BP][r][c])];
  363.     else for(r = 0; r < rows; r++)
  364.         for(c = 0; c < cols; c++)
  365.         buf[r][c] = (byte) colors[gray_lut[image[GRAY][r][c]]];
  366.     return;
  367. }
  368.  
  369. /************************************************/
  370. void
  371. map_mask_to_buf(mask, buf, mb_key, size, draw_pts)
  372. byte *mask, *buf;
  373. int mb_key, size;
  374. LOGIC draw_pts;
  375. {
  376.     register int i;
  377.  
  378.     if(draw_pts) for (i = 0; i < size; i++) {
  379.         if(mask[i] & mb_key) {
  380.             if(mask[i] & m[BUF_PTS].bit_key)
  381.                 buf[i] = (byte) pallet[ORANGE].pixel;
  382.             else buf[i] = (byte) pallet[CWHITE].pixel;
  383.         }
  384.         else {
  385.             if(mask[i] & m[BUF_PTS].bit_key)
  386.                 buf[i] = (byte) pallet[RED].pixel;
  387.             else buf[i] = (byte) pallet[CBLACK].pixel;
  388.         }
  389.     }
  390.     else for (i = 0; i < size; i++) {
  391.         if (mask[i] & mb_key) 
  392.             buf[i] = (byte) pallet[CWHITE].pixel;
  393.         else
  394.             buf[i] = (byte) pallet[CBLACK].pixel;
  395.     }
  396. }
  397.  
  398. /************************************************/
  399. void
  400. blend_images_to_buf(image, mask, buf, mb_key, rows, cols, draw_pts)
  401. u_char ***image, **mask, **buf;
  402. int mb_key, rows, cols;
  403. LOGIC draw_pts;
  404. {
  405.     byte map_rgb_to_xcolor();
  406.  
  407.     register int r, c;
  408.     int intensity;
  409.  
  410.     if(draw_pts) for(r = 0; r < rows; r++)
  411.         for(c = 0; c < cols; c++) {
  412.         if(segal.color)
  413.             intensity = MONO(image[RP][r][c], image[GP][r][c],
  414.                 image[BP][r][c]);
  415.         else intensity = image[GRAY][r][c];
  416.  
  417.         if(mask[r][c] & m[BUF_PTS].bit_key) {
  418.             if(mask[r][c] & mb_key)
  419.                 buf[r][c] = (byte) pallet[ORANGE].pixel;
  420.             else buf[r][c] = (byte) colors[pt_lut[intensity]];
  421.         }
  422.         else {
  423.             if(mask[r][c] & mb_key)
  424.                 buf[r][c] = (byte) colors[blend_lut[intensity]];
  425.             else {
  426.                 if(segal.color)
  427.                     buf[r][c] = (byte) colors[map_rgb_to_xcolor(image[RP][r][c], image[GP][r][c], image[BP][r][c])];
  428.                 else buf[r][c] = (byte) colors[gray_lut[intensity]];
  429.             }
  430.         }
  431.     }
  432.     else for(r = 0; r < rows; r++)
  433.         for(c = 0; c < cols; c++) {
  434.  
  435.         /* define intensity */
  436.         if(segal.color)
  437.             intensity = MONO(image[RP][r][c], image[GP][r][c],
  438.                 image[BP][r][c]);
  439.         else intensity = image[GRAY][r][c];
  440.  
  441.         /* get the right xcolor */
  442.         if(mask[r][c] & mb_key) {
  443.             buf[r][c] = (byte) colors[blend_lut[intensity]];
  444.         }
  445.         else {
  446.             if(segal.color)
  447.                 buf[r][c] = (byte) colors[map_rgb_to_xcolor(image[RP][r][c], image[GP][r][c], image[BP][r][c])];
  448.             else buf[r][c] = (byte) colors[gray_lut[intensity]];
  449.         }
  450.     }
  451. }
  452.  
  453. /************************************************/
  454. void
  455. map_nothing_to_buf(buf, size)
  456. byte *buf;
  457. int size;
  458. {
  459.     int i;
  460.  
  461.     for(i = 0; i < size; i++)
  462.         buf[i] = (byte) colors[(byte) i % 255];
  463. }
  464.  
  465. /*************************************************************/
  466. u_long
  467. standout(col)
  468. int col;
  469. {
  470.    return ((byte)pallet[col].pixel);
  471. }
  472.  
  473. /*************************************************************/
  474. u_long
  475. whitepixel()
  476. {
  477.    return ((byte)pallet[CWHITE].pixel);
  478. }
  479. /*************************************************************/
  480. u_long
  481. blackpixel()
  482. {
  483.    return ((byte)pallet[CBLACK].pixel);
  484. }
  485. /*************************************************************/
  486. int
  487. get_gamma(val, gam)
  488.     byte      val;
  489.     float     gam;
  490. {
  491.     float     newval;
  492.  
  493.     newval = 256. * pow((double) val / 256., (double) (1.0 / gam));
  494.     return (MIN((int) (newval + .5), 255));    /* dont allow values > 255 */
  495. }
  496.  
  497.  
  498. /*************************************************************/
  499. void
  500. gamma_proc(item, value, event)
  501. Panel_item item;
  502. int value;
  503. Event *event;
  504. {
  505.     void map_buffers();
  506.     int i;
  507.     double gammaval;
  508.     static double old_gammaval = -1.0;
  509.     int get_gamma();
  510.  
  511.     gammaval = (float) xv_get(Preferences_pop_preferences_display->set_image_contrast, PANEL_VALUE, NULL) / 10.;
  512.  
  513.     if (gammaval == old_gammaval)
  514.         return;
  515.  
  516.     fprintf(stderr, "xmask: performing gamma with value %.2f \n",
  517.         (float) gammaval);
  518.  
  519.     old_gammaval = gammaval;
  520.  
  521.     apply_gamma(gammaval, noglob, perfect, ncols, mono, rwcolor);
  522.  
  523.     For_all_windows
  524.         map_image_to_colors((byte *) win[i].ximg->data, image_map, win[WIN_VZ].img_size);
  525.  
  526.     /*
  527.     blend(himage.data[0], work_buf[0], (u_char *) blend_image->data, win[WIN_VZ].img_size);
  528.     */
  529.  
  530.     map_buffers();
  531. }
  532.  
  533. /*********************************************************/
  534.  
  535. HSV_to_RGB(hue, sat, val, red, green, blue)
  536. /* written by David Robertson, LBL
  537.  *
  538.  * HSV_to_RGB - converts a color specified by hue, saturation and intensity
  539.  * to r,g,b values.
  540.  * Hue should be in the range 0-360 (0 is red); saturation and intensity
  541.  * should both be in [0,1].
  542.  */
  543.  
  544.     short     hue;
  545.     double    sat, val;
  546.     int      *red, *green, *blue;
  547.  
  548. {
  549.     register double r, g, b;
  550.     int       i;
  551.     register double f, nhue;
  552.     double    p, q, t;
  553.  
  554.     val *= 255.0;
  555.     if (hue == 360)
  556.     nhue = 0.0;
  557.     else
  558.     nhue = (double) hue / 60.0;
  559.     i = (int) nhue;        /* Get integer part of nhue */
  560.     f = nhue - (double) i;    /* And fractional part */
  561.     p = val * (1.0 - sat);
  562.     q = val * (1.0 - sat * f);
  563.     t = val * (1.0 - sat * (1.0 - f));
  564.     switch (i) {
  565.     case 0:
  566.     r = val;
  567.     g = t;
  568.     b = p;
  569.     break;
  570.     case 1:
  571.     r = q;
  572.     g = val;
  573.     b = p;
  574.     break;
  575.     case 2:
  576.     r = p;
  577.     g = val;
  578.     b = t;
  579.     break;
  580.     case 3:
  581.     r = p;
  582.     g = q;
  583.     b = val;
  584.     break;
  585.     case 4:
  586.     r = t;
  587.     g = p;
  588.     b = val;
  589.     break;
  590.     case 5:
  591.     r = val;
  592.     g = p;
  593.     b = q;
  594.     }
  595.  
  596.     *red = (int) (r + 0.5);
  597.     *green = (int) (g + 0.5);
  598.     *blue = (int) (b + 0.5);
  599.  
  600. }
  601.